package edu.xidian.forum.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.xidian.forum.common.Result;
import edu.xidian.forum.dto.LoginDto;
import edu.xidian.forum.dto.RegisterDto;
import edu.xidian.forum.entity.Follow;
import edu.xidian.forum.entity.Post;
import edu.xidian.forum.entity.User;
import edu.xidian.forum.jwt.JwtUtil;
import edu.xidian.forum.mapper.FollowMapper;
import edu.xidian.forum.mapper.TopicMapper;
import edu.xidian.forum.mapper.UserMapper;
import edu.xidian.forum.service.UserService;
import edu.xidian.forum.util.MD5Utils;
import edu.xidian.forum.vo.ProfileVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Date;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Value("${avatar.default}")
    private String avatarDefault;
    @Value("${avatar.server}")
    private String avatarServer;

    @Autowired
    private TopicMapper topicMapper;
    @Autowired
    private FollowMapper followMapper;

    @Override
    public Result<Void> executeRegister(RegisterDto registerDto) {
        User user = baseMapper.selectOne(
                Wrappers.<User>lambdaQuery().eq(
                        User::getUsername, registerDto.getName()));
        if (!ObjectUtils.isEmpty(user)) {
            return Result.failed("Username conflict!");
        }
        user = baseMapper.selectOne(
                Wrappers.<User>lambdaQuery().eq(
                        User::getEmail, registerDto.getEmail()));
        if (!ObjectUtils.isEmpty(user)) {
            return Result.failed("Email conflict!");
        }
        User addUser = User.builder()
                .username(registerDto.getName())
                .alias(registerDto.getName())
                .password(MD5Utils.getPwd(registerDto.getPassword()))
                .avatar(avatarDefault)
                .email(registerDto.getEmail())
                .createTime(new Date())
                .status(true)
                .build();
        baseMapper.insert(addUser);
        return Result.success();
    }

    @Override
    public Result<String> executeLogin(LoginDto loginDto) {
        User user = baseMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, loginDto.getName()));
        if (ObjectUtils.isEmpty(user)) {
            return Result.failed("Account does not exist!!");
        }
        if (!user.getPassword().equals(
                MD5Utils.getPwd(loginDto.getPassword()))) {
            return Result.failed("Password does not match!!");
        }
        return Result.success(JwtUtil.generateToken(user.getUsername()));
    }

    @Override
    public User getUser(String username) {
        return baseMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, username));
    }

    @Override
    public User getUserToFrontend(String username) {
        User user = getUser(username);
        if (user == null) {
            return null;
        }

        user.setAvatar(avatarServer + user.getAvatar());
        return user;
    }


    @Override
    public User checkEmail(String email) {
        return baseMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getEmail, email));
    }

    @Override
    public ProfileVO getProfile(String id) {
        User user = baseMapper.selectById(id);
        if (user == null) return null;

        ProfileVO profile = new ProfileVO(user);
        profile.setAvatar(avatarServer + profile.getAvatar());

        int count = topicMapper.selectCount(new LambdaQueryWrapper<Post>().eq(Post::getUserId, id));
        profile.setTopicCount(count);

        int followers = followMapper.selectCount((new LambdaQueryWrapper<Follow>().eq(Follow::getParentId, id)));
        profile.setFollowerCount(followers);
        return profile;
    }

    @Override
    public Boolean isAdmin(String username) {
        User user = getUser(username);
        return user.getRoleId() != null && user.getRoleId().equals(1);
    }

}
